package com.example.jpa.dao;

import com.example.jpa.entity.BaseEntry;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.PagingAndSortingRepository;
import org.springframework.transaction.annotation.Transactional;

import java.io.Serializable;
import java.util.List;

@NoRepositoryBean
public interface BaseDao<T extends BaseEntry, ID extends Serializable> extends PagingAndSortingRepository<T, ID>, JpaSpecificationExecutor<T>
{
    /*逻辑查找*/
    @Transactional(readOnly = true)
    @Query("select e from #{#entityName} e where e.deleted = false")
    List<T> findAll2Logic();

    /*根据id数组逻辑查找*/
    @Transactional(readOnly = true)
    @Query("select e from #{#entityName} e where e.id in ?1 and e.deleted = false")
    Iterable<T> findAll2Logic(Iterable<ID> ids);

    /*根据id查找实体*/
    @Transactional(readOnly = true)
    @Query("select e from #{#entityName} e where e.id = ?1 and e.deleted = false")
    T findOne2Logic(ID id);

    /*逻辑返回总数据量*/
    @Transactional(readOnly = true)
    @Query("select count(e) from #{#entityName} e where e.deleted = false")
    long count2Logic();

    /*逻辑返回是否存在*/
    @Transactional(readOnly = true)
    default boolean exists2Logic(ID id)
    {
        return findOne2Logic(id) != null;
    }

    /*根据id逻辑删除*/
    @Query("update #{#entityName} e set e.deleted = true where e.id = ?1")
    @Transactional
    @Modifying
    void logic2Delete(ID id);

    /*根据实体逻辑删除*/
    @Transactional
    default void logic2Delete(T entity)
    {
        logic2Delete((ID) entity.getId());
    }

    /*根据实体数组逻辑删除*/
    @Transactional
    default void logic2Delete(Iterable<? extends T> entities)
    {
        entities.forEach(entity -> logic2Delete((ID) entity.getId()));
    }

    /*全量逻辑删除*/
    @Query("update #{#entityName} e set e.deleted = true ")
    @Transactional
    @Modifying
    void logic2DeleteAll();
}
